package com.jiangyg.mall.sentinel;

import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import com.jiangyg.mall.core.support.restful.Result;
import com.jiangyg.mall.core.utils.Logger;
import com.jiangyg.mall.core.utils.WebUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.server.ServerResponse;

import javax.annotation.PostConstruct;

/**
 * 类描述：REACTIVE 服务的 Sentinel 配置
 *
 * @author jiangyg
 * @version 4.0
 * @date 2022-10-08
 */
@Slf4j
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
@ConditionalOnProperty(name = "spring.cloud.sentinel.enabled", matchIfMissing = true)
public class SentinelReactiveWebAutoConfiguration {

    /**
     * 功能描述：设置限流异常处理
     */
    @PostConstruct
    public void setBlockHandler() {
        GatewayCallbackManager.setBlockHandler((exchange, ex) -> {
            // TODO GatewayCallbackManager WebFluxCallbackManager 区别
            // TODO 异常统一处理 和 sentinel 模块
            Result<?> rd;
            if (ex instanceof FlowException) {
                rd = Result.instance("461");
            } else if (ex instanceof DegradeException) {
                rd = Result.instance("462");
            } else if (ex instanceof ParamFlowException) {
                rd = Result.instance("463");
            } else if (ex instanceof SystemBlockException) {
                rd = Result.instance("464");
            } else if (ex instanceof AuthorityException) {
                rd = Result.instance("465");
            } else {
                Logger.error(log, () -> String.format("请求[%s]触发未知限流规则", WebUtils.getRequestPath(exchange)), ex);
                rd = Result.instance("466");
            }
            return ServerResponse
                    .status(HttpStatus.OK)
                    .contentType(MediaType.APPLICATION_JSON)
                    .bodyValue(rd.toJSONString());
        });
    }

}
